package com.gitee.flwwsg.rpc.spi;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
 * SPI 类加载器
 */
public class ServiceSupport {
    //单例缓存
    private final static Map<String, Object> singletonServices = new HashMap<>();
    private final static Logger logger = LoggerFactory.getLogger(ServiceSupport.class);

    //synchronized 是 Java 中的关键字，是利用锁的机制来实现同步的。
    public synchronized static <S> S load(Class<S> service) {
        logger.info("loading class {}\n", service);
        return StreamSupport
                .stream(ServiceLoader.load(service).spliterator(), false)
                .map(ServiceSupport::singletonFilter)
                .findFirst().orElseThrow(ServiceLoadException::new);
    }

    //加载所有服务
    public synchronized static <S> Collection<S> loadAll(Class<S> service) {
        return StreamSupport
                .stream(ServiceLoader.load(service).spliterator(), false)
                .map(ServiceSupport::singletonFilter)
                .collect(Collectors.toList());
    }

    //查找单例
    @SuppressWarnings("unchecked")
    private static <S> S singletonFilter(S service) {
        if (service.getClass().isAnnotationPresent(Singleton.class)) {
            //已经加上 singleton 注解
            String className = service.getClass().getCanonicalName();
            Object singletonInstance = singletonServices.putIfAbsent(className, service);
            return singletonInstance == null ? service : (S) singletonInstance;
        }
        return service;
    }
}
